/* -*- c -*- */
/*
 * vim:syntax=c
 */

#ifndef _NPY_UMATH_LOOPS_H_
#define _NPY_UMATH_LOOPS_H_

#ifndef NPY_NO_EXPORT
    #define NPY_NO_EXPORT NPY_VISIBILITY_HIDDEN
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*
 *****************************************************************************
 **                             BOOLEAN LOOPS                               **
 *****************************************************************************
 */

/*
 * Following functions are defined by umath generator
 * to enable runtime dispatching without the need
 * to redefine them within dsipatch-able sources.
 */
// #define BOOL_invert BOOL_logical_not
// #define BOOL_add BOOL_logical_or
// #define BOOL_bitwise_and BOOL_logical_and
// #define BOOL_bitwise_or BOOL_logical_or
// #define BOOL_logical_xor BOOL_not_equal
// #define BOOL_bitwise_xor BOOL_logical_xor
// #define BOOL_multiply BOOL_logical_and
// #define BOOL_maximum BOOL_logical_or
// #define BOOL_minimum BOOL_logical_and
// #define BOOL_fmax BOOL_maximum
// #define BOOL_fmin BOOL_minimum

typedef struct PyArrayMethod_Context_tag PyArrayMethod_Context;
typedef struct NpyAuxData_tag NpyAuxData;

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_comparison.dispatch.h"
#endif

/**begin repeat
 * #kind = equal, not_equal, greater, greater_equal, less, less_equal#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void BOOL_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_logical.dispatch.h"
#endif

/**begin repeat
 * #kind = logical_and, logical_or, logical_not, absolute#
 */
 NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void BOOL_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat**/

NPY_NO_EXPORT void
BOOL__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

/**begin repeat
 * #kind = isnan, isinf, isfinite#
 **/
NPY_NO_EXPORT void
BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat**/


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_autovec.dispatch.h"
#endif
/**begin repeat
 * #kind = isnan, isinf, isfinite, floor, ceil, trunc#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void BOOL_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat**/

/*
 *****************************************************************************
 **                           INTEGER LOOPS
 *****************************************************************************
 */

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_arithmetic.dispatch.h"
#endif

/**begin repeat
 * #TYPE = UBYTE, USHORT, UINT, ULONG, ULONGLONG,
           BYTE,  SHORT,  INT,  LONG,  LONGLONG#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_divide,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))

NPY_NO_EXPORT int
@TYPE@_divide_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat3**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_modulo.dispatch.h"
#endif

/**begin repeat
 * #TYPE = UBYTE, USHORT, UINT, ULONG, ULONGLONG,
           BYTE,  SHORT,  INT,  LONG,  LONGLONG#
 */
/**begin repeat1
 * #kind = divmod, fmod, remainder#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_comparison.dispatch.h"
#endif

/**begin repeat
 * #TYPE = UBYTE, USHORT, UINT, ULONG, ULONGLONG,
           BYTE,  SHORT,  INT,  LONG,  LONGLONG#
 */
/**begin repeat1
 * #kind = equal, not_equal, greater, greater_equal, less, less_equal#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_autovec.dispatch.h"
#endif
/**begin repeat
 * #TYPE = UBYTE, USHORT, UINT, ULONG, ULONGLONG,
           BYTE,  SHORT,  INT,  LONG,  LONGLONG#
 */
/**begin repeat1
 * #kind = invert, logical_not, conjugate, reciprocal, square, add,
 *         subtract, multiply, bitwise_and, bitwise_or, bitwise_xor,
 *         left_shift, right_shift, logical_and, logical_or,
 *         logical_xor, isnan, isinf, isfinite,
 *         absolute, sign, bitwise_count#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/

/**begin repeat
 * #TYPE = BYTE, SHORT, INT, LONG, LONGLONG#
 */
/**begin repeat1
 * both signed and unsigned integer types
 * #s = , u#
 * #S = , U#
 */
#define @S@@TYPE@_floor_divide @S@@TYPE@_divide
#define @S@@TYPE@_floor_divide_indexed @S@@TYPE@_divide_indexed
#define @S@@TYPE@_fmax @S@@TYPE@_maximum
#define @S@@TYPE@_fmin @S@@TYPE@_minimum
#define @S@@TYPE@_fmax_indexed @S@@TYPE@_maximum_indexed
#define @S@@TYPE@_fmin_indexed @S@@TYPE@_minimum_indexed

NPY_NO_EXPORT void
@S@@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
@S@@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**begin repeat2
 * #kind = floor, ceil, trunc#
 */
#define @S@@TYPE@_@kind@ @S@@TYPE@_positive
/**end repeat2**/

/**begin repeat2
 * Arithmetic
 * #kind = add, subtract, multiply, bitwise_and, bitwise_or, bitwise_xor,
 *          left_shift, right_shift#
 * #OP = +, -,*, &, |, ^, <<, >>#
 */
NPY_NO_EXPORT int
@S@@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args,
                         npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat2**/

/**begin repeat2
 * #kind = maximum, minimum#
 **/
NPY_NO_EXPORT void
@S@@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
@S@@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat2**/

NPY_NO_EXPORT void
@S@@TYPE@_power(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@S@@TYPE@_gcd(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@S@@TYPE@_lcm(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat2**/


/**end repeat1**/
/**end repeat**/

/**begin repeat
 * #kind = equal, not_equal, less, less_equal, greater, greater_equal#
 * #OP = ==, !=, <, <=, >, >=#
 */
NPY_NO_EXPORT void
LONGLONG_Qq_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
NPY_NO_EXPORT void
LONGLONG_qQ_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**end repeat**/


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_unary.dispatch.h"
#endif
/**begin repeat
 * #TYPE = UBYTE, USHORT, UINT, ULONG, ULONGLONG,
 *         BYTE,  SHORT,  INT,  LONG,  LONGLONG#
 */
/**begin repeat1
 * #kind = negative#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/


/*
 *****************************************************************************
 **                             FLOAT LOOPS                                 **
 *****************************************************************************
 */
#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_unary_fp.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #kind = rint, floor, trunc, ceil, sqrt, absolute, square, reciprocal#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_unary_fp_le.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #kind = isnan, isinf, isfinite, signbit#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_unary.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
 */
/**begin repeat1
 * #kind = negative#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_arithm_fp.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * Arithmetic
 * # kind = add, subtract, multiply, divide#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))

NPY_NO_EXPORT int
@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_hyperbolic.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #func = tanh#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@func@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/

// SVML
#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_umath_fp.dispatch.h"
#endif

/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #func = tanh, exp2, log2, log10, expm1, log1p, cbrt, tan, arcsin, arccos, arctan, sinh, cosh, arcsinh, arccosh, arctanh#
 */

NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@func@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))

/**end repeat1**/
/**end repeat**/

/**begin repeat
 * #func = sin, cos, tan, exp, exp2, log, log2, log10, expm1, log1p, cbrt, arcsin, arccos, arctan, sinh, cosh, tanh, arcsinh, arccosh, arctanh#
 */

NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void HALF_@func@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))

/**end repeat**/

/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #func = power, arctan2#
 */

NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@func@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))

/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_trigonometric.dispatch.h"
#endif

/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 *  #func = sin, cos#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@func@, (
    char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)
))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_exponent_log.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * # kind = exp, log, frexp, ldexp#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@, (
  char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)
))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_comparison.dispatch.h"
#endif
/**begin repeat
 *  #TYPE = FLOAT, DOUBLE#
 */
/**begin repeat1
 * #kind = equal, not_equal, less, less_equal, greater, greater_equal#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@, (
  char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)
))
/**end repeat1**/
/**end repeat**/

/**begin repeat
 * Float types
 *  #TYPE = HALF, FLOAT, DOUBLE, LONGDOUBLE#
 *  #c = f, f, , l#
 *  #C = F, F, , L#
 *  #half = 1, 0, 0, 0#
 *  #fd = 0, 1, 1, 0#
 */

/**begin repeat1
 * Arithmetic
 * # kind = add, subtract, multiply, divide#
 * # OP = +, -, *, /#
 */
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat1**/
/**end repeat1**/

/**begin repeat1
 * #kind = logical_and, logical_or#
 * #OP = &&, ||#
 */
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

NPY_NO_EXPORT void
@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**begin repeat1
 * #kind = isnan, isinf, isfinite, signbit, copysign, nextafter, spacing#
 * #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit, npy_copysign, nextafter, spacing#
 * #dispatched = 1, 1, 1, 1, 0, 0, 0#
 **/

#if !@fd@ || !@dispatched@
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
#endif
/**end repeat2**/
/**end repeat1**/

/**begin repeat1
 * #kind = maximum, minimum#
 **/
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat1**/

/**begin repeat1
 * #kind = fmax, fmin#
 **/
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

/**end repeat1**/

NPY_NO_EXPORT void
@TYPE@_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
@TYPE@_floor_divide_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_square(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
@TYPE@_conjugate(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

#if @half@
NPY_NO_EXPORT void
@TYPE@_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
#endif

NPY_NO_EXPORT void
@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_modf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_frexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_ldexp_int64(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat**/

/**begin repeat
 * #TYPE = HALF, LONGDOUBLE#
 */
/**begin repeat1
 * #kind = equal, not_equal, less, less_equal, greater, greater_equal#
 */
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_autovec.dispatch.h"
#endif
/**begin repeat
 * #TYPE = HALF#
 */
/**begin repeat1
 * #kind = absolute#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/
/*
 *****************************************************************************
 **                           COMPLEX LOOPS                                 **
 *****************************************************************************
 */
#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_arithm_fp.dispatch.h"
#endif
/**begin repeat
 * #TYPE = CFLOAT, CDOUBLE#
 */
/**begin repeat1
 * #kind = add, subtract, multiply, conjugate, square#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_unary_complex.dispatch.h"
#endif
/**begin repeat
 * #TYPE = CFLOAT, CDOUBLE#
 */
/**begin repeat1
 * #kind = absolute#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

#define CGE(xr,xi,yr,yi) (xr > yr || (xr == yr && xi >= yi));
#define CLE(xr,xi,yr,yi) (xr < yr || (xr == yr && xi <= yi));
#define CGT(xr,xi,yr,yi) (xr > yr || (xr == yr && xi > yi));
#define CLT(xr,xi,yr,yi) (xr < yr || (xr == yr && xi < yi));
#define CEQ(xr,xi,yr,yi) (xr == yr && xi == yi);
#define CNE(xr,xi,yr,yi) (xr != yr || xi != yi);

/**begin repeat
 * complex types
 * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
 * #c = f, , l#
 * #C = F, , L#
 */

/**begin repeat1
 * arithmetic
 * #kind = add, subtract, multiply#
 */
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT int
C@TYPE@_@kind@_indexed(PyArrayMethod_Context *NPY_UNUSED(context), char *const *args, npy_intp const *dimensions, npy_intp const *steps, NpyAuxData *NPY_UNUSED(func));
/**end repeat1**/

NPY_NO_EXPORT void
C@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**begin repeat1
 * #kind= greater, greater_equal, less, less_equal, equal, not_equal#
 * #OP = CGT, CGE, CLT, CLE, CEQ, CNE#
 */
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

/**begin repeat1
   #kind = logical_and, logical_or#
   #OP1 = ||, ||#
   #OP2 = &&, ||#
*/
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

NPY_NO_EXPORT void
C@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
C@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**begin repeat1
 * #kind = isnan, isinf, isfinite#
 * #func = npy_isnan, npy_isinf, npy_isfinite#
 * #OP = ||, ||, &&#
 **/
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

NPY_NO_EXPORT void
C@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
C@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
C@TYPE@_conjugate(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
C@TYPE@_absolute(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
C@TYPE@_square(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
C@TYPE@__arg(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
C@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**begin repeat1
 * #kind = maximum, minimum#
 * #OP = CGE, CLE#
 */
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

/**begin repeat1
 * #kind = fmax, fmin#
 * #OP = CGE, CLE#
 */
NPY_NO_EXPORT void
C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

/**end repeat**/

#undef CGE
#undef CLE
#undef CGT
#undef CLT
#undef CEQ
#undef CNE

/*
 *****************************************************************************
 **                            DATETIME LOOPS                               **
 *****************************************************************************
 */

NPY_NO_EXPORT void
TIMEDELTA_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/**begin repeat
 * #TYPE = DATETIME, TIMEDELTA#
 */

NPY_NO_EXPORT void
@TYPE@_isnat(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
@TYPE@_isfinite(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

#define @TYPE@_isnan @TYPE@_isnat

NPY_NO_EXPORT void
@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

/**begin repeat1
 * #kind = equal, not_equal, greater, greater_equal, less, less_equal#
 * #OP =  ==, !=, >, >=, <, <=#
 */
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

/**begin repeat1
 * #kind = maximum, minimum, fmin, fmax#
 **/
NPY_NO_EXPORT void
@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/

/**end repeat**/

NPY_NO_EXPORT void
DATETIME_Mm_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));

NPY_NO_EXPORT void
DATETIME_mM_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_m_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
DATETIME_Mm_M_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
DATETIME_MM_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_qm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_md_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_md_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_d_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
TIMEDELTA_mm_qm_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

/* Special case equivalents to above functions */
#define TIMEDELTA_mq_m_floor_divide TIMEDELTA_mq_m_divide
#define TIMEDELTA_md_m_floor_divide TIMEDELTA_md_m_divide
/* #define TIMEDELTA_mm_d_floor_divide TIMEDELTA_mm_d_divide */


#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_autovec.dispatch.h"
#endif
/**begin repeat
 * #TYPE = TIMEDELTA, DATETIME#
 */
/**begin repeat1
 * #kind = isinf#
 */
NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
    (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)))
/**end repeat1**/
/**end repeat**/

/*
 *****************************************************************************
 **                            OBJECT LOOPS                                 **
 *****************************************************************************
 */

/**begin repeat
 * #kind = equal, not_equal, greater, greater_equal, less, less_equal#
 * #OP = EQ, NE, GT, GE, LT, LE#
 */
/**begin repeat1
 * #suffix = , _OO_O#
 */
NPY_NO_EXPORT void
OBJECT@suffix@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
/**end repeat1**/
/**end repeat**/

NPY_NO_EXPORT void
OBJECT_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));

NPY_NO_EXPORT void
PyUFunc_OOO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func);

/*
 *****************************************************************************
 **                            MIN/MAX LOOPS                                **
 *****************************************************************************
 */

#ifndef NPY_DISABLE_OPTIMIZATION
    #include "loops_minmax.dispatch.h"
#endif

//---------- Integers ----------

/**begin repeat
 * #TYPE = BYTE, UBYTE, SHORT, USHORT, INT, UINT,
 *         LONG, ULONG, LONGLONG, ULONGLONG#
 */
/**begin repeat1
 * #kind = maximum, minimum#
 */
 NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

//---------- Float ----------

 /**begin repeat
  * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
  */
/**begin repeat1
 * #kind = maximum, minimum, fmax, fmin#
 */
 NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT void @TYPE@_@kind@,
   (char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data)))
/**end repeat1**/
/**end repeat**/

/*
 *****************************************************************************
 **                              END LOOPS                                  **
 *****************************************************************************
 */
#ifdef __cplusplus
}
#endif
#endif
